spec: re-derive the liveness ledger before its verdicts start warning authors — 3 errors in 33 rows (9.1%), list.tabs flipped to dead - #16542
Merged
Conversation
…/tags to live, view list.tabs to dead Ledger audit ahead of the authorWarn flip. Three corrections, each re-derived against a literal-sha anchor (objectstack 5d55afe, objectui a472b071) with a firing positive control on the same instrument and corpus. validation.label / .description / .tags: dead -> live. The 2026-08-10 note upheld dead on REACHABILITY and named its own falsifier — objectui#4132 wiring ValidationPreview into the embedded editor. That has landed: the standalone door is gone and EmbeddedItemEditor now resolves getMetadataPreview(editAs) and mounts the preview on the live draft, so the read point that never ran, runs. Display keys, settled outright by the previews ruling. view list.tabs: live -> dead. The old note was wrong in both directions. TabBar reads the sub-keys but nothing mounts it — zero production render sites in the whole objectui tree — so authoring list.tabs draws no tab bar; and tabs[].order IS sorted on, which the note called a dead sub-surface. The hotcrm#1307 premise is upheld, not contradicted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno
…ion producer chain The realm marker attributes paths only up to the next clause boundary, so the second and third clauses' paths were being resolved as repo-local and check:liveness reported six unresolvable producer pointers. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T6HeZvT9wdSJD1ZxJb5Eno
Contributor
📓 Docs Drift Check
What this run could not see
Coarse fallback — 130 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
This was referenced Sep 7, 2026
huangyiirene
marked this pull request as ready for review
September 7, 2026 08:50
huangyiirene
enabled auto-merge
September 7, 2026 08:51
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #16362
Clause-②: no — ledger JSON rows plus the generated count table. No export, no key, no accept-set movement. Confirmed mechanically, and both gates proved able to go red (below).
⭐ The error rate
3 wrong out of 33
deadrows re-derived — 9.1%.On the subset that can actually reach an author: 3 of 22 — 13.6%.
Every row was re-derived against a literal-sha anchor (objectstack
5d55afec4d, objectuia472b071from this repo's.objectui-sha) with a positive control fired on the same instrument and the same corpus before any zero was read as a reading. Where a control went dark the reading was discarded and the corpus corrected, not reported.The card says "the 90
deadrows". The ledger holds 94 at the pinned base — and, more importantly, they are not one population:deadwarning ever reach an author?retiredKeytombstonesSo "every
deadrow starts warning every downstream author" is true of 22 rows, not 94. That reframes the blast radius by roughly 4x, and it is why this audit covers all 22 authorable rows rather than 10 sampled ones. The 11 tombstones in the sample are there to keep the denominator honest, not to pad it.Sampled 33 of 94 (35%), spanning 15 of the 22 files that carry
deadrows.Scope item 1 —
list.tabs:live→deadThe old note was wrong in both directions in one sentence, which is the two-direction rot the ledger README warns an entry accumulates:
TabBarreads those sub-keys, but nothing mountsTabBar. At objectuia472b071, everyTabBarrender site in the whole tree is the component's own definition or one of its two test files; zero production sites, zero references underapps/, no component-registry entry.ListViewnever readstabsoff the view schema — its onlylist.tabstoken is a translation-table label, and the toolbar slot whose comments still say "view tabs above" holdsUserFiltersalone. This is theseed.envproducer-gap shape: a real consumer no producer ever calls. Firing control: the same search for the JSX open-tag spelling of ListView returns production render sites on the same corpus and instrument; the pathspec was separately proved to reach nestedapp-shelldirectories before any zero was read.tabs[].orderis sorted on —TabBar.tsx#getVisibleTabsends.sort((a, b) => (a.order ?? 0) - (b.order ?? 0)). The note called it a dead sub-surface.Independent corroboration, already in this repo:
packages/cli/src/utils/i18n-extract.tsscopes its tab-label extractor to a page'sinterfaceConfig.userFilters.tabsand states in so many words thatListViewSchema.tabshas no reader in either repo — deliberately emitting no scaffolding keys for it.Why not
liveon the two author-time readers.packages/lint/src/validate-list-view-field-refs.ts#checkTabsandpackages/metadata-protocol/src/metadata-diagnostics.tsboth walktabs[].filter[].fieldfor reference integrity, and the protocol normalizes filter operators inside it. None delivers the key's declared effect ("Tab definitions for multi-tab view interface"). That is theroute_generationprecedent verbatim — an enum validated at the door and then ignored is accept/reject, which this ledger has always kept separate from liveness — and the opposite ofdashboard.widgets[].suppressWarnings, whose declared effect is the lint read.🔵 The hotcrm premise is UPHELD — nothing to file there
hotcrm#1307's
test/view-tab-label-inert.test.tsasserts the object-view switcher never readslist.tabs. The switcher isplugin-view/src/ViewTabBar.tsx, which takes aviews: ViewTabItem[]prop (saved views) and reads notabskey at all. My re-derivation lands on the same side as that test, so the losing side isview.json— which is in scope and is corrected here.Scope item 2 — the sampled
deadauditThe three errors, all in
validation.json, all the same shape. The 2026-08-10 sweep uphelddeadon reachability, not on the read:ValidationPreviewgenuinely read and renderedlabel,descriptionandtags, but the only route that mounted it was the standalonevalidationresource door, and ADR-0088 had retired that kind — so on the governed path (a rule embedded in its object) the preview was never handed a draft.That note named its own falsifier, and the re-derivation found it had fired:
objectui#4132 has landed, and did both halves. The standalone door is gone (
anchors.tsnow records that there is no standalone Validations group and no create affordance), and the preview is wired into the embedded editor instead:EmbeddedItemEditorresolvesgetMetadataPreview(editAs)and mounts it withdraftset to the live authored value, while the__object_validationanchor setseditAstovalidation. The read point that never ran, runs. Under the 2026-08-10 ruling these are display keys and are settled outright. They stay docs-shaped and are still not author-warned.The 30 rows that held did so on measurement, not assumption. Highlights:
realtime_subscription.*— all six settled by one producer measurement:SubscriptionSchemahas zero references outsidepackages/specin either repo, so nothing ever parses one. Controls fired both sides (ViewSchemaoutside spec;ViewTabSchemain 8 objectui files). Thesub.channelread inin-memory-realtime-adapter.tsis the adapter's own record type, exactly as that row's note already predicted.permission.rowLevelSecurity[].label/.description/.tags—PermissionPreviewonly counts the array (${rls.length} RLS rules) and descends no further. Same instrument that re-gradedvalidation, opposite answer.view.label— held on both of its stated re-open conditions still being unmet: the named-view tab bar returns null when the entry map holds one entry or fewer, and the preview injects exactly one, and the registeredObjectViewRendererpasses norenderListView.qa.scenarios[].tags—os testships three flags (--url,--token,--fail-on-empty); none selects scenarios. Correctly dead, and the sharpest genuine enforce-or-remove row in the set.One row flagged, not changed:
manifest.integrityisdeadwhileos plugin publishrefuses on a digest mismatch — a real local enforcer. Its own note is aware of this and explicitly routes the flip to the #11331 chain rather than a rider. Left alone as out of scope, but the maintainer should know the ledger holds a self-declared open question there.Scope item 3 — the one
live-elsewhererowmanifest.runtimere-derived. Local half holds exactly: the only reads are the two CLI echo lines the note names (build.ts:127,publish.ts:110— the latter drifted 16 lines, symbol intact), bothruntime: ${manifest.runtime ?? 'unset'}, and there is noruntime ===dispatch anywhere in the repo. Control fired (transport ===returns a hit on the same instrument). All four gate-executable criteria pass, attestation 9 days old against a 180-day window.Gates
check:livenessgreen — and it earned it: it caught a real defect in my first draft (sixproducerpointers that did not resolve, because the realm marker attributes paths only up to the next clause boundary and I wrote one marker for three clauses). That is a useful counterweight to the measured false-green on row contents: the gate does check evidence shape, it simply cannot check a verdict.check:objectui-pin-citationsindependently validates all 8 asserting objectui citations against.objectui-sha.Clause ② proved, not read as a bare green — each gate mutated and re-run with no rebuild in between, so neither leg is the vacuous kind that moves its own baseline:
check:api-surfacecheck:authorable-surfaceBoth mutations were proved on disk by blob-hash inequality against the
HEADblob, and both restores proved by hash equality plus an emptygit diff HEAD— never by an exit code.54 derived gate families, 53 run, all green. The one not run is
check:dual-build-cjs-loads, which exited 3 printing "⛔ This is NOT a pass: nothing was measured" — it needs a whole-repopnpm build(81 packages lackdist). Recorded as NOT MEASURED and declared to CI, not as a pass.Lint, narrowed and declared. All four changed paths are outside eslint's configured population — its own
isPathIgnoredsays so, and--format jsonreturns 4 results, 0 errors, 4 warnings, every one of them "File ignored because no matching configuration was supplied". The config never enables type-aware linting for any file (stated ateslint.config.mjs:327, with its own measured positive control), so this diff cannot move the verdict on a file it did not touch. Measured against final commitda68a1d.Changeset
Present —
.changeset/liveness-ledger-reaudit-16362.md, patch on@objectstack/spec. Four ledger rows changed, so one is owed;skip-changesetwould be wrong here.Generated by Claude Code